package com.cyanite.playlv2;

import com.cyanite.playlv2.app.LoadableListActivityWithViewAndHeader;
import com.cyanite.playlv2.util.NotificationsUtil;
import com.cyanite.playlv2.widget.FriendListAdapter;
import com.cyanite.playlv2.widget.SegmentedButton;
import com.cyanite.playlv2.widget.SegmentedButton.OnClickListenerSegmentedButton;
import com.cyanite.playlv2api.types.Group;
import com.cyanite.playlv2api.types.Trip;
import com.cyanite.playlv2api.types.User;
import com.cyanite.playlv2.R;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;

/**
 * To be used when a user has some friends in common. We show two lists, by default
 * the first list is 'friends in common'. The second list is all friends. This is
 * expected to be used with a fully-fetched user object, so the friends in common
 * group should already be fetched. The full 'all friends' list is fetched separately
 * within this activity.
 *
 * If the user has no friends in common, then just use UserDetailsFriendsActivity
 * directly.
 *
 */
public class UserDetailsFriendsInCommonActivity extends LoadableListActivityWithViewAndHeader {

    public static final String EXTRA_USER_PARCEL = PlayLv2.PACKAGE_NAME
        + ".UserDetailsFriendsInCommonActivity.EXTRA_USER_PARCEL";
    public static final String EXTRA_TRIP_PARCEL = PlayLv2.PACKAGE_NAME
        + ".UserDetailsFriendsInCommonActivity.EXTRA_TRIP_PARCEL";
    public static final String EXTRA_TRIP_FOCUSED_USER = PlayLv2.PACKAGE_NAME
        + ".UserDetailsFriendsInCommonActivity.EXTRA_TRIP_FOCUSED_USER";

    private StateHolder mStateHolder;
    private FriendListAdapter mListAdapter;
    private ScrollView mLayoutEmpty;
    private static final int MENU_REFRESH = 0;

    private BroadcastReceiver mLoggedOutReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            finish();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        registerReceiver(mLoggedOutReceiver, new IntentFilter(PlayLv2.INTENT_ACTION_LOGGED_OUT));

        mStateHolder = new StateHolder();
        if (getIntent().hasExtra(EXTRA_TRIP_PARCEL)) {
             mStateHolder.setTrip((Trip)getIntent().getParcelableExtra(EXTRA_TRIP_PARCEL));      
        } else if (getIntent().hasExtra(EXTRA_USER_PARCEL)) {
             mStateHolder.setUser((User)getIntent().getParcelableExtra(EXTRA_USER_PARCEL));      
        } else {
            finish();
            return;
        }
        if (getIntent().hasExtra(EXTRA_TRIP_FOCUSED_USER)) {
            mStateHolder.setIsTripUsers(true);
        }

        ensureUi();
    }

    @Override
    public void onPause() {
        super.onPause();

        if (isFinishing()) {
            mStateHolder.cancelTasks();
            mListAdapter.removeObserver();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mLoggedOutReceiver);
    }

    private void ensureUi() {
        LayoutInflater inflater = LayoutInflater.from(this);

        mLayoutEmpty = (ScrollView)inflater.inflate(R.layout.user_details_friends_activity_empty,
                null);
        mLayoutEmpty.setLayoutParams(new LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT));

        mListAdapter = new FriendListAdapter(this,
            ((PlayLv2) getApplication()).getRemoteResourceManager());
        if (mStateHolder.getFriendsInCommonOnly()) {
            if (mStateHolder.getUser().getFriendsInCommon() != null 
                    && !mStateHolder.getIsTripUsers() ){
                mListAdapter.setGroup(mStateHolder.getUser().getFriendsInCommon());
            } else if (mStateHolder.getTrip().getFriendsInCommon() != null 
                    && mStateHolder.getIsTripUsers() ){
                mListAdapter.setGroup(mStateHolder.getTrip().getFriendsInCommon());
            } else{
                setEmptyView(mLayoutEmpty);
            }
        } else {
            mListAdapter.setGroup(mStateHolder.getAllFocusUsers());
            if (mStateHolder.getAllFocusUsers().size() == 0) {
                if (mStateHolder.getRanOnce()) {
                    setEmptyView(mLayoutEmpty);
                } else {
                    setLoadingView();
                }
            }
        }

        SegmentedButton buttons = getHeaderButton();
        buttons.clearButtons();
        if (mStateHolder.getIsTripUsers())  {
            buttons.addButtons(
                    getString(R.string.user_details_friends_in_common_common_friends),
                    getString(R.string.user_details_friends_in_common_all_friends));
        } else {
            buttons.addButtons(
                    getString(R.string.trip_details_friends_in_common_common_friends),
                    getString(R.string.trip_details_friends_in_common_all_friends));
        }
        if (mStateHolder.getFriendsInCommonOnly()) {
            buttons.setPushedButtonIndex(0);
        } else {
            buttons.setPushedButtonIndex(1);
        }

        buttons.setOnClickListener(new OnClickListenerSegmentedButton() {
            @Override
            public void onClick(int index) {
                if (index == 0) {
                    mStateHolder.setFriendsInCommonOnly(true);
                    if ( mStateHolder.getTrip().getFriendsInCommon() != null ) {
                        mListAdapter.setGroup(mStateHolder.getTrip().getFriendsInCommon());
                    } else {
                        setEmptyView(mLayoutEmpty);
                        mListAdapter.setGroup(null);
                    }                    
                } else {
                    mStateHolder.setFriendsInCommonOnly(false);
                    mListAdapter.setGroup(mStateHolder.getAllFocusUsers());
                    if (mStateHolder.getAllFocusUsers().size() < 1) {
                        if (mStateHolder.getRanOnce()) {
                            setEmptyView(mLayoutEmpty);
                        } else {
                            setLoadingView();
                            mStateHolder.startTaskAllFocusUsers(UserDetailsFriendsInCommonActivity.this);
                        }
                    }
                }

                mListAdapter.notifyDataSetChanged();
                getListView().setSelection(0);
            }
        });

        ListView listView = getListView();
        listView.setAdapter(mListAdapter);
        listView.setSmoothScrollbarEnabled(false);
        listView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                User user = (User) parent.getAdapter().getItem(position);
                Intent intent = new Intent(UserDetailsFriendsInCommonActivity.this, UserDetailsActivity.class);
                intent.putExtra(UserDetailsActivity.EXTRA_USER_PARCEL, user);
                intent.putExtra(UserDetailsActivity.EXTRA_SHOW_ADD_FRIEND_OPTIONS, true);
                startActivity(intent);
            }
        });

        if (mStateHolder.getIsRunningTaskAllFocusUsers()) {
            setProgressBarIndeterminateVisibility(true);
        } else {
            setProgressBarIndeterminateVisibility(false);
        }

        setTitle(getString(R.string.user_details_friends_in_common_title, mStateHolder.getTrip().getUserName()));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(Menu.NONE, MENU_REFRESH, Menu.NONE, R.string.refresh)
            .setIcon(R.drawable.ic_menu_refresh);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case MENU_REFRESH:
                if (!mStateHolder.getFriendsInCommonOnly()) {
                    mStateHolder.startTaskAllFocusUsers(this);
                }
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void onStartTaskAllFriends() {
        mStateHolder.setIsRunningTaskAllFocusUsers(true);
        setProgressBarIndeterminateVisibility(true);
        setLoadingView();
    }

    private void onTaskAllFriendsComplete(Group<User> allFriends, Exception ex) {
        setProgressBarIndeterminateVisibility(false);
        mStateHolder.setRanOnce(true);
        mStateHolder.setIsRunningTaskAllFocusUsers(false);

        if (allFriends != null) {
            mStateHolder.setAllFocusUsers(allFriends);
        } else {
            NotificationsUtil.ToastReasonForFailure(this, ex);
        }

        SegmentedButton buttons = getHeaderButton();
        if (buttons.getSelectedButtonIndex() == 1) {
            mListAdapter.setGroup(mStateHolder.getAllFocusUsers());
            if (mStateHolder.getAllFocusUsers().size() == 0) {
                if (mStateHolder.getRanOnce()) {
                    setEmptyView(mLayoutEmpty);
                } else {
                    setLoadingView();
                }
            }
        }
    }

    /**
     * Gets friends of the current user we're working for.
     */
    private static class TaskAllFocusUsers extends AsyncTask<Void, Void, Group<User>> {

        private UserDetailsFriendsInCommonActivity mActivity;
        private String mTripId;
        private String mUserId;
        private boolean mIsTripUsers;
        private Exception mReason;

        public TaskAllFocusUsers(UserDetailsFriendsInCommonActivity activity, String userId,
                String tripId, boolean isTripUsers) {
            mActivity = activity;
            mTripId = tripId;
            mUserId = userId;
            mIsTripUsers = isTripUsers;
        }

        @Override
        protected void onPreExecute() {
            mActivity.onStartTaskAllFriends();
        }

        @Override
        protected Group<User> doInBackground(Void... params) {
            try {
                PlayLv2 playlv2 = (PlayLv2) mActivity.getApplication();
                if (mIsTripUsers)
                    return playlv2.getPlayLv2Api().friendsInTrip(mTripId);
                else
                    return playlv2.getPlayLv2Api().friends(mUserId);
            } catch (Exception ex) {
                mReason = ex;
                return null;
            }            
        }

        @Override
        protected void onPostExecute(Group<User> allFriends) {
            if (mActivity != null) {
                mActivity.onTaskAllFriendsComplete(allFriends, mReason);
            }
        }

        @Override
        protected void onCancelled() {
            if (mActivity != null) {
                mActivity.onTaskAllFriendsComplete(null, mReason);
            }
        }

        public void setActivity(UserDetailsFriendsInCommonActivity activity) {
            mActivity = activity;
        }
    }

    private static class StateHolder {
        private Trip mTrip;
        private User mUser;
        private Group<User> mAllFocusUsers;
        private TaskAllFocusUsers mTaskAllFocusUser;
        private boolean mIsRunningTaskAllFocusUsers;
        private boolean mRanOnceTaskAllFocusUsers;
        private boolean mFriendsInCommonOnly;
        private boolean mIsTripUsers;

        public StateHolder() {
            mAllFocusUsers = new Group<User>();
            mIsRunningTaskAllFocusUsers = false;
            mRanOnceTaskAllFocusUsers = false;
            mFriendsInCommonOnly = true;
            mTrip = new Trip();
            mUser = new User();
            mIsTripUsers = false;
        }

        public Trip getTrip() {
            return mTrip;
        }

        public void setTrip(Trip trip) {
            mTrip = trip;
        }
        
        public User getUser()   {
            return mUser;
        }
        
        public void setUser(User user)  {
            mUser = user;
        }
        
        public boolean getIsTripUsers() {
            return mIsTripUsers;
        }
        
        public void setIsTripUsers(boolean isTripUsers)   {
            mIsTripUsers = isTripUsers;
        }

        public Group<User> getAllFocusUsers() {
            return mAllFocusUsers;
        }

        public void setAllFocusUsers(Group<User> allFocusUsers) {
            mAllFocusUsers = allFocusUsers;
        }

        public void startTaskAllFocusUsers(UserDetailsFriendsInCommonActivity activity) {
            if (!mIsRunningTaskAllFocusUsers) {
                mIsRunningTaskAllFocusUsers = true;
                mTaskAllFocusUser = new TaskAllFocusUsers(activity, mUser.getId(),
                                                                    mTrip.getId(), mIsTripUsers);
                mTaskAllFocusUser.execute();
            }
        }

        public boolean getIsRunningTaskAllFocusUsers() {
            return mIsRunningTaskAllFocusUsers;
        }

        public void setIsRunningTaskAllFocusUsers(boolean isRunning) {
            mIsRunningTaskAllFocusUsers = isRunning;
        }

        public void cancelTasks() {
            if (mTaskAllFocusUser != null) {
                mTaskAllFocusUser.setActivity(null);
                mTaskAllFocusUser.cancel(true);
            }
        }

        public boolean getRanOnce() {
            return mRanOnceTaskAllFocusUsers;
        }

        public void setRanOnce(boolean ranOnce) {
            mRanOnceTaskAllFocusUsers = ranOnce;
        }

        public boolean getFriendsInCommonOnly() {
            return mFriendsInCommonOnly;
        }

        public void setFriendsInCommonOnly(boolean friendsInCommonOnly) {
            mFriendsInCommonOnly = friendsInCommonOnly;
        }
    }
}
